home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / AutoBin Source / binhex.c < prev    next >
Text File  |  1993-12-09  |  14KB  |  507 lines

  1. #define FILE_NUM 4
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /************************************************************************
  4.  * functions to convert files to binhex and back again
  5.  * much of this code is patterned after xbin by Dave Johnson, Brown University
  6.  * Some is lifted straight from xbin.  Our thanks to Dave & Brown.
  7.  ************************************************************************/
  8.  
  9. // this code was then lifted from eudora.                                         mxm
  10. // 12-9-93 made it stand alone and work with drop shell code. mxm
  11.  
  12.  
  13. typedef unsigned char *UPtr;
  14. typedef Handle UHandle;
  15. #include <string.h>
  16. #include "DSGlobals.h"
  17. #define True     1
  18. #define False 0
  19. #define LDRef(h) (*h)
  20. #define UL(h)
  21. #define BINHEX_OPEN    5807
  22. #define BUFFER_SIZE    4096
  23. #define MEM_ERR    6417
  24. #define BINHEX_READ    5811
  25. #define NuHandle NewHandle
  26. #define NuPtr NewPtr
  27. #define SetHandleBig SetHandleSize
  28.  
  29. #define FILL(pb,name,vRef,dirId) do {                                     \
  30.     (pb).ioNamePtr = name;                                                                \
  31.     (pb).ioVRefNum = vRef;                                                                \
  32.     (pb).ioDirID = dirId;                                                                 \
  33.     } while (0)
  34.     
  35. Boolean DontTranslate;    /* don't use translation tables */
  36. Boolean CommandPeriod;    /* has cmd-. been pressed lately? */
  37.  
  38.  
  39.  
  40. /************************************************************************
  41.  * Declarations for private routines
  42.  ************************************************************************/
  43. void comp_q_crc_out(unsigned short c);
  44. short EncodeDataChar(Byte c, UPtr toSpot);
  45. int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
  46.                                                                                 Handle codedBuffer,UPtr name);
  47. /************************************************************************
  48.  * six to eight bit conversion table
  49.  ************************************************************************/
  50. Byte BinHexTable[64] = {
  51.                 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
  52.                 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x31, 0x32,
  53.                 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x40, 0x41,
  54.                 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  55.                 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, 0x52,
  56.                 0x53, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5a, 0x5b,
  57.                 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
  58.                 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x71, 0x72 };
  59. unsigned long CalcCrc;
  60. Byte State86;
  61. Byte SavedBits;
  62. Byte LineLength;
  63.     
  64. #define LCODE(dc)  codedSpot += EncodeDataChar(dc,*codedBuffer+codedSpot)
  65. #define CODE(dc) do {                                                                                                     \
  66.     LCODE(dc);                                                                                                                        \
  67.     if ((Byte)dc==(Byte)0x90) LCODE(0);                                                                     \
  68.     comp_q_crc_out(dc);                                                                                                     \
  69.     } while (0)
  70. #define CODESHORT(ds) do {short copy=ds; UPtr cp=&ds;                                     \
  71.     CODE(cp[0]); CODE(cp[1]);} while(0)
  72. #define CODELONG(dl) do {long copy=dl; UPtr cp=&dl;                                         \
  73.     CODE(cp[0]); CODE(cp[1]); CODE(cp[2]); CODE(cp[3]);} while(0)
  74.     
  75. short MyResolveAlias(short *vRef,long *dirId,UPtr name,Boolean *wasAlias);
  76. short SendTrans(short lines ,Ptr buffptr,short  buffsize);
  77. void WriteZero(UPtr pointer,long size);
  78. void WarnUser (short id,short code);
  79. void ComposeRString (void );
  80.  
  81. void GetRString (void );
  82. long  GetRLong (long id);
  83. short FSHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm);
  84. short RFHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm);
  85.         void FileSystemError (short id,StringPtr name,short err);
  86.  
  87.  short HGetFileInfo(short vRef,long dirId,UPtr name,HFileInfo *hfi);
  88.  int SendBinHex(short vRef,long dirId,UPtr name);
  89. void      PushProgress(StringPtr name);
  90.          
  91. void    ByteProgress(StringPtr text,short start,long amount);
  92.     void      PopProgress(StringPtr name);
  93.  
  94. //--------------------------------------------------------------------
  95.     void      PushProgress(StringPtr name)
  96. //--------------------------------------------------------------------
  97.     {
  98.         SetPort(gSplashScreen);
  99.         EraseRect(&gSplashScreen->portRect);
  100.         MoveTo(10,18);
  101.         DrawString(name);
  102.         
  103.     }
  104.     
  105. //--------------------------------------------------------------------
  106.     void      PopProgress(StringPtr name)
  107. //--------------------------------------------------------------------
  108.     {
  109.         SetPort(gSplashScreen);
  110.         //EraseRect(&gSplashScreen->portRect);
  111.         MoveTo(10,38);
  112.         DrawString(name);
  113.         
  114.     }
  115.  
  116. //--------------------------------------------------------------------
  117.     void          ByteProgress(StringPtr text,short sub,long amount)
  118. //--------------------------------------------------------------------
  119.     {
  120.         Str255 temp;
  121.         Rect r;
  122.         static long curamount;
  123.         
  124.         if (amount!=0)  
  125.             curamount = amount;
  126.             
  127.         curamount += sub;
  128.         
  129.         SetPort(gSplashScreen);
  130.         r = gSplashScreen->portRect;
  131.         r.top = 20;
  132.         r.bottom = 40;
  133.         EraseRect(&r);
  134.         MoveTo(10,38);
  135.         if (text)
  136.             DrawString(text);
  137.         NumToString(curamount,&temp);
  138.         r.top = 40;
  139.         r.bottom = 60;
  140.         EraseRect(&r);
  141.         MoveTo(10,58);
  142.         DrawString(temp);
  143.  
  144.     }
  145. //--------------------------------------------------------------------
  146.     short SendTrans(short lines ,Ptr buffptr,short  buffsize)
  147. //--------------------------------------------------------------------
  148. {
  149.     short oe;
  150.     long count = buffsize;
  151.     oe = FSWrite(gRefNum,&count,buffptr);
  152.     return  oe;
  153.         
  154. }
  155. /**********************************************************************
  156.  * write zeroes over an area of memory
  157.  **********************************************************************/
  158. void WriteZero(UPtr pointer,long size)
  159. {
  160.     while (size--) *pointer++ = 0;
  161. }
  162. void  WarnUser (short id,short code)
  163.   {
  164.      
  165.  }
  166.  
  167. void ComposeRString (void)
  168.   {
  169.  
  170.  }
  171.  
  172.  
  173. void  GetRString (void)
  174.   {
  175.  
  176.  }
  177. long  GetRLong (long id)
  178.   {
  179.         return id;
  180.  }
  181.  
  182. /************************************************************************
  183.  * FSHOpen - like FSOpen, but takes a dirId and permissions, too.
  184.  ************************************************************************/
  185. short FSHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm)
  186. {
  187.     HIOParam pb;
  188.     int err;
  189.     Str255 newName;
  190.     
  191.     //PCopy(newName,name);
  192.     BlockMove(name,newName,(*name) + 1);
  193.     if (err=MyResolveAlias(&vRefN,&dirId,newName,nil)) return(err);
  194.     pb.ioNamePtr = newName;
  195.     pb.ioVRefNum = vRefN;
  196.     pb.ioPermssn = perm;
  197.     pb.ioMisc = nil;
  198.     ((HFileParam *)&pb)->ioDirID = dirId;
  199.     err = PBHOpen(&pb,False);
  200.     if (!err) *refN = pb.ioRefNum;
  201.     return(err);
  202. }
  203.  
  204. /************************************************************************
  205.  * RFHOpen - like RFOpen, but with dirId and permissions
  206.  ************************************************************************/
  207. short RFHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm)
  208. {
  209.     HIOParam pb;
  210.     int err;
  211.     
  212.     pb.ioCompletion = nil;
  213.     pb.ioNamePtr = name;
  214.     pb.ioVRefNum = vRefN;
  215.     pb.ioVersNum = 0;
  216.     pb.ioPermssn = perm;
  217.     pb.ioMisc = nil;
  218.     ((HFileParam *)&pb)->ioDirID = dirId;
  219.     err = PBHOpenRF(&pb,False);
  220.     if (!err) *refN = pb.ioRefNum;
  221.     return(err);
  222. }
  223.  
  224.  
  225. //-----------------------------------------------------------------------
  226.         void FileSystemError (short id,StringPtr name,short err)
  227. //-----------------------------------------------------------------------
  228.   {
  229.       ParamText(name,"\p","\p","\p");
  230.         Alert(1003,nil);
  231.         
  232.  }
  233.  
  234.  
  235.  
  236.  
  237.  /************************************************************************
  238.  * MyResolveAlias - resolve an alias
  239.  ************************************************************************/
  240. short MyResolveAlias(short *vRef,long *dirId,UPtr name,Boolean *wasAlias)
  241. {
  242. }
  243.  
  244. //-----------------------------------------------------------------------
  245.  short HGetFileInfo(short vRef,long dirId,UPtr name,HFileInfo *hfi)
  246. //-----------------------------------------------------------------------
  247. {
  248.     short err,oe;
  249.     Str255 newName;
  250.     
  251.     //PCopy(newName,name);
  252.     BlockMove(name,newName,(*name) + 1);
  253.     
  254. //    if (err=MyResolveAlias(&vRef,&dirId,newName,nil)) return(err);
  255.     WriteZero(hfi,sizeof(*hfi));
  256.     FILL(*hfi,newName,vRef,dirId);
  257.     
  258.     oe = PBHGetFInfo(hfi,False);
  259.  
  260.     
  261.     return(oe);
  262. }
  263.  
  264. /************************************************************************
  265.  * SendBinHex - send a file as BinHex data                                
  266.  ************************************************************************/
  267. int SendBinHex(short vRef,long dirId,UPtr name)
  268. {
  269.     short refN=0;
  270.     UHandle dataBuffer=nil;
  271.     UHandle codedBuffer=nil;
  272.     short dataSize;
  273.     short codedSize;
  274.     short codedSpot;
  275.     int err;
  276.     HFileInfo hfp;
  277.     Str255 scratch;
  278.     UPtr spot;
  279.     
  280.     
  281.     /*
  282.      * find the file, and get info
  283.      */
  284.     err = HGetFileInfo(vRef,dirId,name,&hfp);
  285.     if (err) {FileSystemError(BINHEX_OPEN,name,err); goto done;}
  286.     
  287.     /*
  288.      * allocate the buffers
  289.      */
  290.     codedSize = GetRLong(BUFFER_SIZE);
  291.     dataSize = codedSize/3;
  292.     if (!(dataBuffer = (UHandle)NuHandle(dataSize)) || !(codedBuffer=(UHandle)NuHandle(codedSize)))
  293.         {WarnUser(MEM_ERR,MemError()); goto done;}
  294.  
  295.     //ComposeRString(scratch,BINHEX_PROG_FMT,name);
  296.     PushProgress(name);
  297.     ByteProgress(scratch,0,hfp.ioFlLgLen+hfp.ioFlRLgLen);
  298.  
  299.     /*
  300.      * send the header
  301.      */
  302.     //GetRString(scratch,BINHEX_OUT);
  303.     strcpy(scratch,"\p\r(This file must be converted with BinHex 4.0)\r\r:");
  304.     
  305.     if (err=SendTrans(1,scratch+1,*scratch)) goto done;
  306.         
  307.     /*
  308.      * send the file information
  309.      */
  310.     DontTranslate = True;
  311.     LineLength = 1;
  312.     State86 = CalcCrc = codedSpot = 0;
  313.     name[*name+1] = 0;
  314.     for (spot=name;*spot;spot++)
  315.         CODE(*spot);
  316.     CODE(0);
  317.     CODELONG(hfp.ioFlFndrInfo.fdType);
  318.     CODELONG(hfp.ioFlFndrInfo.fdCreator);
  319.     CODESHORT(hfp.ioFlFndrInfo.fdFlags);
  320.     CODELONG(hfp.ioFlLgLen);
  321.     CODELONG(hfp.ioFlRLgLen);
  322.     {
  323.         unsigned short tempCrc;
  324.         comp_q_crc_out(0);
  325.         comp_q_crc_out(0);
  326.         tempCrc = CalcCrc&0xffff;
  327.         CODESHORT(tempCrc);
  328.         CalcCrc = 0;
  329.     }
  330.     if (err=SendTrans(1,LDRef(codedBuffer),codedSpot)) goto done;
  331.     codedSpot = 0;
  332.     UL(codedBuffer);
  333.     
  334.     /*
  335.      * data fork
  336.      */
  337.     if (!vRef)
  338.         {FileSystemError(BINHEX_OPEN,name,0);goto done;}
  339.     if (err = FSHOpen(name,vRef,dirId,&refN,fsRdPerm))
  340.         {FileSystemError(BINHEX_OPEN,name,err); goto done;}
  341.     err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
  342.     if (err) goto done;
  343.  
  344.     /*
  345.      * resource fork
  346.      */
  347.     if (refN) FSClose(refN);
  348.     refN = 0;
  349.     if (err = RFHOpen(name,vRef,dirId,&refN,fsRdPerm)){
  350.             FileSystemError(BINHEX_OPEN,name,err);
  351.             goto done;
  352.     }
  353.     err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
  354.     if (err) goto done;
  355.  
  356.     /*
  357.      * leftovers
  358.      */
  359.     if (State86) CODE(0);
  360.     (*codedBuffer)[codedSpot++] = ':';
  361.     for (err=0;err<*NewLine;) {
  362.         (*codedBuffer)[codedSpot++] = NewLine[++err]; 
  363.     }
  364.     err = SendTrans(1,LDRef(codedBuffer),codedSpot);
  365.     
  366.     
  367. done:
  368.     if (refN) FSClose(refN);
  369.     if (dataBuffer) DisposHandle(dataBuffer);
  370.     if (codedBuffer) DisposHandle(codedBuffer);
  371.     PopProgress("\pDone");
  372.     DontTranslate = False;
  373.     return(err);    
  374. }
  375.  
  376. /************************************************************************
  377.  * BinHexFork - send one fork of a file as BinHex data                                
  378.  ************************************************************************/
  379. int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
  380.                                                                                 Handle codedBuffer,UPtr name)
  381. {
  382.     long dataEnd;
  383.     short codedSpot=0;
  384.     int err;
  385.     unsigned char *spot;
  386.     int errWas;
  387.     
  388.     do
  389.     {
  390.         dataEnd = dataSize;
  391.         err = FSRead(refN,&dataEnd,LDRef(dataBuffer));
  392.         if (!err || err==eofErr)
  393.         {
  394.             errWas = err;
  395.             for (spot = *dataBuffer; spot<*dataBuffer+dataEnd; spot++)
  396.                 CODE(*spot);
  397.             err=SendTrans(1,LDRef(codedBuffer),codedSpot);
  398.             UL(codedBuffer);
  399.             codedSpot = 0;
  400.             if (!err) err = errWas;
  401.             ByteProgress(nil,-dataEnd,0);
  402.         }
  403.         UL(dataBuffer);
  404.         if (err && err!=eofErr && !CommandPeriod)
  405.             FileSystemError(BINHEX_READ,name,err);
  406.     }
  407.     while (!err);
  408.     
  409.     if (err==eofErr)
  410.     {
  411.         {
  412.             unsigned short tempCrc;
  413.             comp_q_crc_out(0);
  414.             comp_q_crc_out(0);
  415.             tempCrc = CalcCrc&0xffff;
  416.             CODESHORT(tempCrc);
  417.             CalcCrc = 0;
  418.         }
  419.         err=SendTrans(1,LDRef(codedBuffer),codedSpot);
  420.         UL(codedBuffer);
  421.     }
  422.     
  423.     return(err==eofErr ? noErr : err);
  424. }
  425.  
  426. /************************************************************************
  427.  * EncodeDataChar - encode an 8-bit data char into a six-bit buffer
  428.  * returns the number of valid encoded characters generated
  429.  ************************************************************************/
  430. short EncodeDataChar(Byte c, UPtr toSpot)
  431. {
  432.     UPtr spotWas=toSpot;
  433.     UPtr nSpot;
  434. #define ADDNEWLINE() do {                                                                             \
  435.     LineLength = 0;                                                                                             \
  436.     for (nSpot=NewLine+1;nSpot<=NewLine+*NewLine;nSpot++)                 \
  437.         *toSpot++ = *nSpot;                                                                                 \
  438.     } while (0)
  439.  
  440.     switch (State86++)
  441.     {
  442.         case 0:
  443.             *toSpot++ = BinHexTable[(c>>2)&0x3f];
  444.             SavedBits = (c&0x3)<<4;
  445.             if (++LineLength == 64) ADDNEWLINE();
  446.             break;
  447.         case 1:
  448.             *toSpot++ = BinHexTable[SavedBits | ((c>>4)&0xf)];
  449.             SavedBits = (c&0xf)<<2;
  450.             if (++LineLength == 64) ADDNEWLINE();
  451.             break;
  452.         case 2:
  453.             *toSpot++ = BinHexTable[SavedBits | ((c>>6)&0x3)];
  454.             if (++LineLength == 64) ADDNEWLINE();
  455.             *toSpot++ = BinHexTable[c&0x3f];
  456.             if (++LineLength == 64) ADDNEWLINE();
  457.             State86 = 0;
  458.             break;
  459.     }
  460.     return(toSpot-spotWas);
  461.  
  462. /************************************************************************
  463.  * comp_q_crc_out - lifted from xbin
  464.  ************************************************************************/
  465. #define BYTEMASK 0xff
  466. #define BYTEBIT 0x100
  467. #define WORDMASK 0xffff
  468. #define WORDBIT 0x10000
  469. #define CRCCONSTANT 0x1021
  470.  
  471. void comp_q_crc_out(unsigned short c)
  472. {
  473.                 register unsigned long temp = CalcCrc;
  474.  
  475. /* Never mind why I call it WOP... */
  476. #define WOP { \
  477.                                 c <<= 1; \
  478.                                 if ((temp <<= 1) & WORDBIT) \
  479.                                                 temp = (temp & WORDMASK) ^ CRCCONSTANT; \
  480.                                 temp ^= (c >> 8); \
  481.                                 c &= BYTEMASK; \
  482.                 }
  483.                 WOP;
  484.                 WOP;
  485.                 WOP;
  486.                 WOP;
  487.                 WOP;
  488.                 WOP;
  489.                 WOP;
  490.                 WOP;
  491.                 CalcCrc = temp;
  492. }
  493.  
  494. //void xmain(void)  
  495. //{  
  496. //NewLine[0]=1;  
  497. //NewLine[1]=13;  
  498. //NewLine[2]=0;  
  499. //  
  500. //    Create("\pTest binhex out",-1,'R*ch','TEXT');  
  501. //    FSOpen("\pTest binhex out",-1,&gRefNum);  
  502. //    SendBinHex(-1,0,"\pAUX:TestBinhex");  
  503. //    FSClose(gRefNum);  
  504. //}  
  505. //  
  506.